#ifndef __THREAD_H__
#define __THREAD_H__

#include <stdio.h>
#include <stdint.h>
#include <pthread.h>
#include "redobject.h"

#ifdef __CYGWIN__
/* use the native semaphore in Windows, reduce the dependency to Cygwin */
#	include <windows.h>
#else
#	include <semaphore.h>
#	define RED_SEM_NAMES		32
#endif

/* synchronization */

typedef volatile int RedSpin;

RED_EXPORT void RedSpin_Acquire(RedSpin *self);
RED_EXPORT void RedSpin_Release(RedSpin *self);

typedef struct _RedMutex
{
	pthread_mutex_t		mutex;
	pthread_mutexattr_t	attrs;
} RedMutex;

RED_EXPORT void RedMutex_Free(RedMutex *self);
RED_EXPORT void RedMutex_Init(RedMutex *self);
RED_EXPORT void RedMutex_Acquire(RedMutex *self);
RED_EXPORT void RedMutex_Release(RedMutex *self);

typedef struct _RedSemaphore
{
#ifdef __CYGWIN__
	HANDLE	 semaphore;
#else
	char	 name[RED_SEM_NAMES];
	sem_t	*semaphore;
#endif
} RedSemaphore;

RED_EXPORT void RedSemaphore_Free(RedSemaphore *self);
RED_EXPORT void RedSemaphore_Init(RedSemaphore *self, int count);
RED_EXPORT void RedSemaphore_Wait(RedSemaphore *self);
RED_EXPORT void RedSemaphore_Signal(RedSemaphore *self);

/* threading */

typedef RedObject *(* RedThreadFunction)(RedObject *args);

typedef struct _RedThread
{
	RedObject_HEAD

	RedObject			*args;
	RedObject			*retval;
	RedThreadFunction	 function;

	char				 daemon;
	char				 throwing;
	RedObject			*exception;

	int64_t				 tid;
	pthread_attr_t		 attr;
	pthread_cond_t		 cond;
	pthread_mutex_t		 mutex;
	pthread_t			 thread;
} RedThread;

RED_EXPORT RedThread *RedThread_Self(void);
RED_EXPORT RedObject *RedThread_Join(RedThread *thread);
RED_EXPORT RedThread *RedThread_Create(RedThreadFunction func, RedObject *args, char daemon);

/* generic */

RED_EXPORT void Red_FreeThreadManager(void);
RED_EXPORT char Red_InitThreadManager(void);

#endif /* __THREAD_H__ */
